package com.example.util;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.JWTUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT工具类
 * 统一的JWT token生成和验证工具
 */
@Slf4j
@Component
public class JwtUtil {

    @Value("${jwt.secret}")
    private String secret;

    @Value("${jwt.expiration:86400000}")  // 默认24小时
    private Long expiration;

    /**
     * 生成JWT token
     * @param userId 用户ID
     * @param username 用户名
     * @return JWT token
     */
    public String generateToken(Long userId, String username) {
        long now = System.currentTimeMillis();
        long expireTime = now + expiration;

        Map<String, Object> payload = new HashMap<>();
        payload.put("userId", userId);
        payload.put("username", username);
        payload.put(JWTPayload.ISSUED_AT, now);       // 签发时间
        payload.put(JWTPayload.EXPIRES_AT, expireTime); // 过期时间

        return JWTUtil.createToken(payload, secret.getBytes());
    }

    /**
     * 验证JWT token
     * @param token JWT token
     * @return 是否有效
     */
    public boolean validateToken(String token) {
        try {
            return JWTUtil.verify(token, secret.getBytes());
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 从token中获取用户ID
     * @param token JWT token
     * @return 用户ID
     */
    public Long getUserIdFromToken(String token) {
        try {
            JWT jwt = JWTUtil.parseToken(token);
            return (Long) jwt.getPayload("userId");
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 从token中获取用户名
     * @param token JWT token
     * @return 用户名
     */
    public String getUsernameFromToken(String token) {
        try {
            JWT jwt = JWTUtil.parseToken(token);
            return jwt.getPayload("username")
                      .toString();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 检查token是否过期
     * @param token JWT token
     * @return 是否过期
     */
    public boolean isTokenExpired(String token) {
        try {
            JWT jwt = JWTUtil.parseToken(token);
            Object expireObj = jwt.getPayload(JWTPayload.EXPIRES_AT);

            long expireMillis = (expireObj instanceof Number)
                    ? ((Number) expireObj).longValue()
                    : Long.parseLong(expireObj.toString());

            return expireMillis < System.currentTimeMillis();
        } catch (Exception e) {
            log.error("判断token是否过期失败", e);
            return true;
        }
    }



    /**
     * 从token中获取过期时间
     * @param token JWT token
     * @return 过期时间
     */
    public Date getExpirationDateFromToken(String token) {
        try {
            JWT jwt = JWTUtil.parseToken(token);
            Object expireObj = jwt.getPayload(JWTPayload.EXPIRES_AT);
            long expireMillis = (expireObj instanceof Number)
                    ? ((Number) expireObj).longValue()
                    : Long.parseLong(expireObj.toString());

            return new Date(expireMillis);
        } catch (Exception e) {
            return null;
        }
    }



    /**
     * 从token中获取签发时间
     * @param token JWT token
     * @return 签发时间
     */
    public Date getIssuedAtDateFromToken(String token) {
        try {
            JWT jwt = JWTUtil.parseToken(token);
            return DateUtil.date(Convert.toLong(jwt.getPayload(JWTPayload.ISSUED_AT)));
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 提取Authorization头中的token
     * @param authHeader Authorization头的值
     * @return 提取的token，如果格式不正确返回null
     */
    public String extractTokenFromHeader(String authHeader) {
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            return authHeader.substring(7);
        }
        return authHeader;
    }
}
